package hu.monitor.remoting.server;

import hu.monitor.remoting.InvocationContext;
import hu.monitor.remoting.InvokerInterceptor;

import java.io.IOException;
import java.util.Map;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginContext;

public class LoginInvokerInterceptor implements InvokerInterceptor {

	@Override
	public Object intercept(final InvocationContext invocationContext) throws Throwable {
		final Map<String, Object> attributes = invocationContext.getAttributes();
		Subject subject = null;
		if (attributes.containsKey("hu.monitor.user")) {
			final int agentId = (Integer)attributes.get("hu.monitor.user");
			final AgentIdCallbackHandler handler = new AgentIdCallbackHandler(agentId);
			final LoginContext context = new LoginContext("Monitor", handler);
			context.login();
			subject = context.getSubject();
		}
		try {
			return invocationContext.invoke();
		} finally {
			if (subject != null) {
				final LoginContext context = new LoginContext("Monitor", subject);
				context.logout();
			}
		}
	}

	private static class AgentIdCallbackHandler implements CallbackHandler {
		private final int agentId;

		public AgentIdCallbackHandler(final int agentId) {
			this.agentId = agentId;
		}

		@Override
		public void handle(final Callback[] callbacks) throws IOException, UnsupportedCallbackException {
			for (final Callback callback: callbacks) {
				if (callback instanceof NameCallback) {
					((NameCallback)callback).setName(String.valueOf(this.agentId));
				} else if (callback instanceof PasswordCallback) {
					((PasswordCallback)callback).setPassword("dummy".toCharArray());
				}
			}
		}

	}
}
